#region Using directives

using System;
using System.Collections.Generic;
using System.Windows.Forms;

#endregion
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting;
using System.IO;
using Thinxoft.HttpLib;
//using System.Threading;
using System.Collections.Specialized;
using System.Runtime.Remoting.Lifetime;


namespace HTTPReqMan
{
    public class RequestHandler : IPCObject, HTTPMsgAPI.IRequestHandler
    {
        public bool Ping()
        {
            return true;
        }

        public byte[] HandleRequest(byte[] stream, Dictionary<string, string> hdrs, Dictionary<string, string> pParams)
        {
            //use the lates settings to process request                
            ServerState state = Program.XState;
            HttpApplicationCollection applications = state.Applications;

            try
            {
                //load into headers name value collection
                NameValueCollection headers = new NameValueCollection();
                foreach (KeyValuePair<string, string> header in hdrs)
                {
                    headers.Add(header.Key, header.Value);
                }

                //load into post parameters namevalue collection
                NameValueCollection postParams = new NameValueCollection();
                foreach (KeyValuePair<string, string> header in pParams)
                {
                    postParams.Add(header.Key, header.Value);
                }

                //find the resource (pull from cache)
                string resource = hdrs["resource"];
                string query = hdrs["query"];
                string root = Path.GetPathRoot(resource);

                bool invalidChars =  CheckForInvalidCharacters(state, query);

                if (invalidChars)
                {
                    return HttpResponse.WriteResponse("Invalid query string characters", HttpResponse.ResponseCode.Ok);
                }
                else
                {
                    
                    HttpResource requestResource = GetResource(resource);//state.Applications.FindHostApplication(resource);
                    if (requestResource != null)
                    {

                        return Monitor.GetResource(requestResource, query, resource, ref headers, ref  postParams);
                    }
                    else
                    {
                        return HttpResponse.WriteResponse("Could not find resource " + resource, HttpResponse.ResponseCode.Ok);
                    }
                }

               
            }
            catch (InvalidDataException id)
            {
                return HttpResponse.WriteResponse("Possible XSS script has ben blocked <br>  To turn of advanced security please use administration tool.", HttpResponse.ResponseCode.Ok);
            }
            catch (Exception ex)
            {
                return HttpResponse.WriteResponse("An error of type " + ex.Message + " occured.  " + ex.StackTrace, HttpResponse.ResponseCode.Ok);

            }
        }

        HttpResource GetResource(string resource)
        {
            foreach (KeyValuePair<string, Dictionary<string, HttpResource>> applicationList in Monitor.Resources)
            {
                string appName = applicationList.Key;
                Dictionary<string, HttpResource>  resourceList = applicationList.Value;
                string resourceKey = string.Format("{1}", appName, resource);
                HttpApplication app = Program.XState.Applications[appName];
                string alternate = resourceKey.TrimEnd('/');
               
                
                if (resourceList.ContainsKey(alternate))
                {
                    resourceKey = alternate;
                }

                if (resourceList.ContainsKey(resourceKey))
                {
                    
                    HttpResource rs = resourceList[resourceKey];
                    if (rs == null)
                        rs = resourceList[resourceKey + "/"];


                    if (rs.ResourceType == "http")
                    {
                        return rs;
                    }
                    else if(rs.ResourceType == "default")
                    {
                        DefaultResource dres = (DefaultResource)rs;
                        foreach (string doc in dres.DefaultDocuments)
                        {
                            string target = dres.Offset + "/"+ doc;
                            if (resourceList.ContainsKey(target))
                            {
                                return resourceList[target];
                            }
                        }
                        return dres;                       
                    }
                    
                }
            }
           
            return null;            
        }

        private bool CheckForInvalidCharacters(ServerState state, string query)
        {
            ////filter out bad characters (or throw exception)
            string badchars = "~!@#$^&*():}{[]<>`";
            List<char> bc = new List<char>(badchars.ToCharArray());
            bool response = false;
            foreach (char c in query)
            {
                if (badchars.Contains(c.ToString()))
                {
                    if (state.XedusSettings.BlockXSS)
                    {
                        response = true;                        
                    }
                }
            }
            return response;

        }
    }

}
